/*******************************************************************************
 * Software Name : Android Simple Downloader
 *
 * Copyright © 2012 Rinvay Tang
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.rinvay.asdownloader.ui;

import java.io.File;
import java.util.ArrayList;

import com.rinvay.asdownloader.R;
import com.rinvay.asdownloader.platform.persistent.DownloadTaskDAO;
import com.rinvay.asdownloader.service.DownloadService;
import com.rinvay.filedownload.FileDownloadListener;
import com.rinvay.filedownload.FileDownloadManager;
import com.rinvay.filedownload.model.DownloadTask;
import com.rinvay.utils.FileUtil;
import com.rinvay.utils.MIMEManager;
import com.rinvay.utils.logger.Logger;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Service;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;

/**
 * asdownloader main page
 * @author Rinvay.T
 * @date 2012-3-29
 * @time 上午1:10:54
 */
public class ASDownloaderActivity extends Activity
{
    private static final String TAG = "ASDownloaderActivity";

    private FileDownloadManager downloadMgr = null;

    private static final String directory = "/mnt/sdcard/asdownload";

    private TabHost tabhost = null;

    private ArrayList<DownloadTask> downloadingTaskes = null;
    private ArrayList<DownloadTask> completedTaskes = null;

    private ListView downloadingList = null;
    private ListView completedList = null;

    private String taskUrl = "";
    private String fileName = "";

    private String selectedtaskuuid = "";

    private static final int MESSAGE_DOWNLOAD_START = 0;
    private static final int MESSAGE_DOWNLOAD_PROCESSING = MESSAGE_DOWNLOAD_START + 1;
    private static final int MESSAGE_DOWNLOAD_COMPLETE = MESSAGE_DOWNLOAD_PROCESSING + 1;
    private static final int MESSAGE_DOWNLOAD_FAILED = MESSAGE_DOWNLOAD_COMPLETE + 1;

    private Handler handler = new Handler() {

        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what)
            {
            case MESSAGE_DOWNLOAD_START:
                DownloadTask task = (DownloadTask) msg.obj;
                if (!downloadingTaskes.contains(task)) {
                    downloadingTaskes.add(task);
                }
                ((DownloadAdapter) downloadingList.getAdapter())
                        .notifyDataSetChanged();
                break;
            case MESSAGE_DOWNLOAD_PROCESSING:
                String uuid = (String) msg.obj;
                ((DownloadAdapter) downloadingList.getAdapter())
                        .notifyDataSetChanged();
                break;
            case MESSAGE_DOWNLOAD_COMPLETE:
                uuid = (String) msg.obj;
                Logger.info(TAG, "onDownloadTransferred " + uuid);
                for (int i = 0, len = downloadingTaskes.size(); i < len; i++) {
                    task = downloadingTaskes.get(i);
                    if (uuid != null && uuid.equals(task.getUUId())) {
                        DownloadTaskDAO.getInstance().updateDownloadTask(task);
                        boolean removed = downloadingTaskes.remove(task);
                        Logger.info(TAG, task.getFileName()
                                + " removed from downloadingTaskes " + removed);
                        if (!completedTaskes.contains(task)) {
                            completedTaskes.add(task);
                            Logger.info(TAG, "add task " + task.getFileName()
                                    + " to ompletedTaskes ");
                        }
                        break;
                    }
                }
                ((DownloadAdapter) downloadingList.getAdapter())
                        .notifyDataSetChanged();
                ((DownloadAdapter) completedList.getAdapter())
                        .notifyDataSetChanged();

                break;
            case MESSAGE_DOWNLOAD_FAILED:
                uuid = (String) msg.obj;
                task = downloadMgr.findTaksByUUID(uuid);
                Toast.makeText(getBaseContext(), task.getFileName() + " 下载失败!",
                        Toast.LENGTH_LONG).show();
                ((DownloadAdapter) downloadingList.getAdapter())
                        .notifyDataSetChanged();

                break;
            }
        }

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        Logger.info(TAG, "onCreate");

        setContentView(R.layout.main);

        initViews();

        Intent intent = getIntent();
        if (ACTION_NEW_TASK.equals(intent.getAction())) {
            taskUrl = intent.getStringExtra("url");
            fileName = intent.getStringExtra("filename");
            showDialog(DIALOG_NEW_TASK);
        }

        startService(new Intent(this, DownloadService.class));
        bindService(new Intent(this, DownloadService.class), serviceConn,
                Service.BIND_AUTO_CREATE);
    }

    protected void onNewIntent(Intent intent) {
        Logger.info(TAG, "onNewIntent!!! ");
        super.onNewIntent(intent);
    }

    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConn);
    }

    private void initViews() {
        tabhost = (TabHost) findViewById(android.R.id.tabhost);
        tabhost.setup();
        tabhost.addTab(tabhost
                .newTabSpec("download")
                .setIndicator("Downloading",
                        getResources().getDrawable(R.drawable.downloading))
                .setContent(R.id.list_downloading));
        tabhost.addTab(tabhost
                .newTabSpec("completed")
                .setIndicator("Completed",
                        getResources().getDrawable(R.drawable.complete))
                .setContent(R.id.list_complete));

        downloadingList = (ListView) findViewById(R.id.list_downloading);
        downloadingList
                .setOnCreateContextMenuListener(new OnCreateContextMenuListener() {

                    public void onCreateContextMenu(ContextMenu menu, View v,
                            ContextMenuInfo menuInfo) {
                        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
                        long id = info.id;
                        menu.setHeaderTitle("下载功能");
                        menu.add(0, OP_DOWNLOAD, 0, "下载");
                        menu.add(0, OP_PAUSE, 0, "暂停");
                        menu.add(0, OP_DELETE, 0, "删除");
                        menu.add(0, OP_CANCEL, 0, "取消");
                    }
                });

        completedList = (ListView) findViewById(R.id.list_complete);
        completedList
                .setOnCreateContextMenuListener(new OnCreateContextMenuListener() {

                    public void onCreateContextMenu(ContextMenu menu, View v,
                            ContextMenuInfo menuInfo) {
                        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
                        long id = info.id;
                        menu.setHeaderTitle("下载功能");
                        menu.add(0, OP_DOWNLOAD, 0, "下载");
                        menu.add(0, OP_PAUSE, 0, "暂停");
                        menu.add(0, OP_DELETE, 0, "删除");
                        menu.add(0, OP_CANCEL, 0, "取消");
                    }
                });

    }

    private FileDownloadListener fdListener = new FileDownloadListener() {

        public void onDownloadProcessing(String uuid) {
//            if(handler.hasMessages(MESSAGE_DOWNLOAD_PROCESSING, uuid)) {
//                return;
//            }
            Message msg = new Message();
            msg.what = MESSAGE_DOWNLOAD_PROCESSING;
            msg.obj = uuid;
            handler.sendMessage(msg);
        }

        public void onDownloadTransferred(final String uuid) {
            Message msg = new Message();
            msg.what = MESSAGE_DOWNLOAD_COMPLETE;
            msg.obj = uuid;
            handler.sendMessage(msg);
        }

        public void onDownloadFailed(String uuid) {
            Logger.info(TAG, "onDownloadFailed " + uuid);
            Message msg = new Message();
            msg.what = MESSAGE_DOWNLOAD_FAILED;
            msg.obj = uuid;
            handler.sendMessage(msg);
        }

    };

    private ServiceConnection serviceConn = new ServiceConnection() {

        public void onServiceDisconnected(ComponentName name) {
            Logger.info(TAG, "Service disconnected!");
            downloadMgr.removeListener(fdListener);
            ((DownloadAdapter) downloadingList.getAdapter())
                    .notifyDataSetInvalidated();
            ((DownloadAdapter) completedList.getAdapter())
                    .notifyDataSetInvalidated();
        }

        public void onServiceConnected(ComponentName name, IBinder service) {
            Logger.info(TAG, "Service connected!");
            downloadMgr = ((DownloadService.DownloadBinder) service)
                    .getDownloadMgr();
            downloadMgr.addListener(fdListener);

            downloadingTaskes = new ArrayList<DownloadTask>();
            completedTaskes = new ArrayList<DownloadTask>();

            ArrayList<DownloadTask> tasks = downloadMgr.getResourceList();
            for (int i = 0, len = tasks.size(); i < len; i++) {
                DownloadTask task = tasks.get(i);
                if (task.isTaskFinished()
                        || DownloadTask.STATE_FINISHED == task.getState()) {
                    completedTaskes.add(task);
                } else {
                    downloadingTaskes.add(task);
                }
            }

            DownloadAdapter adapter = new DownloadAdapter(downloadingTaskes);
            downloadingList.setAdapter(adapter);

            DownloadAdapter completedadapter = new DownloadAdapter(
                    completedTaskes);
            completedList.setAdapter(completedadapter);

        }
    };

    public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
                .getMenuInfo();
        int position = info.position;
        ListView displayed;
        if ("download".equals(tabhost.getCurrentTabTag())) {
            displayed = downloadingList;
        } else {
            displayed = completedList;
        }
        DownloadTask task = (DownloadTask) displayed.getAdapter().getItem(
                position);
        Logger.info(TAG,
                "onContextItemSelected-" + position + "-" + task.getFileName()
                        + "-" + item.getTitle());
        switch (item.getItemId())
        {
        case OP_DOWNLOAD:
            downloadMgr.resumeResourceDownload(task);
            if (completedTaskes.contains(task)) {
                boolean removed = completedTaskes.remove(task);
                Logger.info(TAG, "task " + task.getFileName()
                        + " removed from completedTaskes" + removed);
            }

            if (!downloadingTaskes.contains(task)) {
                downloadingTaskes.add(task);
                Logger.info(TAG, "task " + task.getFileName()
                        + " add to downloadingTaskes");
            }

            ((DownloadAdapter) downloadingList.getAdapter())
                    .notifyDataSetChanged();
            ((DownloadAdapter) completedList.getAdapter())
                    .notifyDataSetChanged();
            break;
        case OP_PAUSE:
            downloadMgr.pauseResouseDownload(task);
            DownloadTaskDAO.getInstance().updateDownloadTask(task);
            ((DownloadAdapter) downloadingList.getAdapter())
                    .notifyDataSetChanged();
            ((DownloadAdapter) completedList.getAdapter())
                    .notifyDataSetChanged();
            break;
        case OP_DELETE:
            selectedtaskuuid = task.getUUId();
            showDialog(DIALOG_DELETE_TASK);
            break;
        case OP_CANCEL:
            break;
        }

        return super.onContextItemSelected(item);
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        Logger.info(TAG, "onOptionsItemSelected");
        switch (item.getItemId())
        {
        case R.id.new_task:
            Logger.info(TAG, "new task");
            taskUrl = "";
            fileName = "";
            showDialog(DIALOG_NEW_TASK);
            break;
        case R.id.view_web:
            Logger.info(TAG, "start web view");
            Intent intent = new Intent(this, WebViewActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
            break;
        case R.id.exit:
            Logger.info(TAG, "exit");
            finish();
            stopService(new Intent(this, DownloadService.class));
            break;
        }
        return super.onOptionsItemSelected(item);
    }

    private static final int DIALOG_NEW_TASK = 0;
    private static final int DIALOG_DELETE_TASK = DIALOG_NEW_TASK + 1;

    protected Dialog onCreateDialog(int id) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        switch (id)
        {
        case DIALOG_NEW_TASK:
            View view = View.inflate(getBaseContext(),
                    R.layout.dialog_new_task, null);
            final EditText etTaskUrl = (EditText) view
                    .findViewById(R.id.et_taskurl);
            final EditText etFileName = (EditText) view
                    .findViewById(R.id.et_filename);
            builder.setView(view);
            builder.setTitle("新建任务");
            builder.setPositiveButton("确定",
                    new DialogInterface.OnClickListener() {

                        public void onClick(DialogInterface dialog, int which) {
                            if (downloadMgr == null) {
                                Toast.makeText(getApplicationContext(),
                                        "Service not connected",
                                        Toast.LENGTH_LONG);
                                return;
                            }
                            String taskUrl = etTaskUrl.getText().toString();
                            String filename = etFileName.getText().toString();
                            createTask(taskUrl, filename);
                        }
                    });
            builder.setNegativeButton("取消",
                    new DialogInterface.OnClickListener() {

                        public void onClick(DialogInterface dialog, int which) {
                        }
                    });
            return builder.create();
        case DIALOG_DELETE_TASK:
            View delview = View.inflate(getBaseContext(),
                    R.layout.dialog_delete_task, null);
            final CheckBox deletefile = (CheckBox) delview
                    .findViewById(R.id.cb_filedelete);
            builder.setView(delview);
            builder.setTitle("删除任务");
            builder.setPositiveButton("确定",
                    new DialogInterface.OnClickListener() {

                        public void onClick(DialogInterface dialog, int which) {
                            if (downloadMgr == null) {
                                Toast.makeText(getApplicationContext(),
                                        "Service not connected",
                                        Toast.LENGTH_LONG);
                                return;
                            }
                            boolean delete = deletefile.isChecked();
                            deleteTask(selectedtaskuuid, delete);

                        }
                    });
            builder.setNegativeButton("取消",
                    new DialogInterface.OnClickListener() {

                        public void onClick(DialogInterface dialog, int which) {
                        }
                    });
            return builder.create();
        }
        return super.onCreateDialog(id);
    }

    protected void onPrepareDialog(int id, Dialog dialog) {
        switch (id)
        {
        case DIALOG_NEW_TASK:
            EditText etTaskUrl = (EditText) dialog
                    .findViewById(R.id.et_taskurl);
            etTaskUrl.setText(taskUrl);
            EditText etFileName = (EditText) dialog
                    .findViewById(R.id.et_filename);
            etFileName.setText(fileName);
            break;
        case DIALOG_DELETE_TASK:

            break;
        }

        super.onPrepareDialog(id, dialog);
    }

    private void deleteTask(String uuid, boolean deletefile) {
        DownloadTask task = downloadMgr.findTaksByUUID(uuid);
        downloadMgr.deleteResouseDownload(task);

        boolean removed = completedTaskes.remove(task);
        Logger.info(TAG, task.getFileName() + " removed from completedTaskes "
                + removed);

        removed = downloadingTaskes.remove(task);
        Logger.info(TAG, task.getFileName()
                + " removed from downloadingTaskes " + removed);

        ((DownloadAdapter) downloadingList.getAdapter())
                .notifyDataSetInvalidated();
        ((DownloadAdapter) completedList.getAdapter())
                .notifyDataSetInvalidated();

        DownloadTaskDAO.getInstance().deleteDownloadTask(task);

        if (deletefile) {
            File file = new File(task.getFileDirectory(), task.getFileName());
            boolean isdeleted = file.delete();
            if (isdeleted) {
                Toast.makeText(this, "文件 " + task.getFileName() + " 删除成功",
                        Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(this, "文件 " + task.getFileName() + " 删除失败",
                        Toast.LENGTH_LONG).show();

            }
        }

    }

    private void createTask(String taskUrl, String filename) {
        DownloadTask task = downloadMgr.createResourse(taskUrl, directory,
                filename, 3);
        Logger.info(TAG, "createTask:" + task.toString());

        DownloadTaskDAO.getInstance().insertDownloadTask(task);

        downloadMgr.startResourceDownload(task);
        Message msg = new Message();
        msg.what = MESSAGE_DOWNLOAD_START;
        msg.obj = task;
        handler.sendMessage(msg);

    }

    private class DownloadAdapter extends BaseAdapter
    {
        private ArrayList<DownloadTask> displayed;

        public DownloadAdapter(ArrayList<DownloadTask> list) {
            displayed = list;
        }

        public int getCount() {
            if (displayed != null) {
                return displayed.size();
            }
            return 0;
        }

        public Object getItem(int position) {
            if (displayed != null && position < getCount()) {
                return displayed.get(position);
            }
            return null;
        }

        public long getItemId(int position) {

            return 0;
        }

        public View getView(int position, View v, ViewGroup parent) {
            if (v == null) {
                ViewHolder holder = new ViewHolder();
                v = View.inflate(getApplicationContext(), R.layout.list_item,
                        null);

                holder.type = (ImageView) v.findViewById(R.id.res_type);
                holder.name = (TextView) v.findViewById(R.id.res_name);
                holder.progress = (ProgressBar) v
                        .findViewById(R.id.res_progress);
                holder.info = (TextView) v.findViewById(R.id.task_info);
//                holder.operate = (ImageView) v.findViewById(R.id.task_control);

                v.setTag(holder);

            }

            ViewHolder holder = (ViewHolder) v.getTag();
            final DownloadTask dt = (DownloadTask) getItem(position);
            if (dt == null) {
                return v;
            }
            holder.type.setImageResource(getResourceType(dt.getFileName()));
            holder.name.setText(dt.getFileName());

            if (dt.isTaskFinished()) {
                holder.progress.setVisibility(View.GONE);
            } else {
                holder.progress.setVisibility(View.VISIBLE);
            }
            if (dt.getSize() <= 0) {
                holder.progress.setProgress(0);
            } else {

                int progress = dt.getCurLength() * 100 / dt.getSize();
                holder.progress.setProgress(progress);
            }

            holder.info.setText(getRTInfo(dt));
//            holder.operate.setOnClickListener(new OnClickListener() {
//                public void onClick(View v) {
//                    downloadMgr.startResourceDownload(dt);
//                }
//            });

            return v;
        }

        /**
         * 实时任务信息
         * @return
         */
        private String getRTInfo(DownloadTask task) {
            StringBuffer buffer = new StringBuffer();
            if (task.getSize() > 0) {
                buffer.append(FileUtil.FormetFileSize(task.getSize()));
            } else {
                buffer.append("未知大小");
            }
            if (task.getState() != DownloadTask.STATE_DOWNLOADING) {
                return buffer.toString();
            }
            buffer.append(" ").append(task.getSpeed()).append("k/s");

            return buffer.toString();
        }

        private int getResourceType(String name) {
            name = name.toLowerCase();
            int resId;
            String mime = MIMEManager.getMimeType(MIMEManager
                    .getFileExtension(name));
            if (MIMEManager.isAudioType(mime)) {
                resId = R.drawable.music;
            } else if (MIMEManager.isImageType(mime)) {
                resId = R.drawable.pictrue;
            } else if (MIMEManager.isVideoType(mime)) {
                resId = R.drawable.video;
            } else {
                resId = R.drawable.other;
            }

            return resId;
        }

        class ViewHolder
        {
            /**
             * 资源类型，图片，音频，视频。。。
             */
            public ImageView type;
            /**
             * 资源名称
             */
            public TextView name;
            /**
             * 下载进度
             */
            public ProgressBar progress;
            /**
             * 下载信息
             */
            public TextView info;
            /**
             * 下载控制
             */
//            public ImageView operate;
        }

    }

    public static final String ACTION_NEW_TASK = "action_new_task";

    private static final int OP_DOWNLOAD = 1;
    private static final int OP_PAUSE = OP_DOWNLOAD + 1;
    private static final int OP_DELETE = OP_PAUSE + 1;
    private static final int OP_CANCEL = OP_DELETE + 1;
}
